package sg.nus.iss.vmcs.controllers;

import java.util.ArrayList;

import sg.nus.iss.vmcs.VMCSException;
import sg.nus.iss.vmcs.dao.VmcsDAOFactory;
import sg.nus.iss.vmcs.gui.GUIChangeManager;
import sg.nus.iss.vmcs.gui.GUIChangeManagerEvent;
import sg.nus.iss.vmcs.models.Coin;
import sg.nus.iss.vmcs.models.CoinRegistry;

/**
 * 
 * This class is assumed to have received the coin from the mechanical coin slot and
 * the weight sensor has weighed the input coin and a new coin instance is created 
 * with empty value and measured weight.
 * 
 * @author Philip
 * @author Raj
 */
public class CoinReceiver {
	
	/** Array to hold coins that have been entered for the transaction */
	private ArrayList<Coin> coins;
	
	/** The total amount of money inserted for a transaction */
	private int totalInserted;
	
	/** The standard set of coins */
	private CoinRegistry cReg;
		
	/** The controller for this class */
	private TransactionController transCtrl;
	
	/**
	 * Creates a new instance of Coin Receiver
	 * @param transCtrl Reference to the transaction controller
	 */
	public CoinReceiver(TransactionController transCtrl) {
		resetCoinVariables();
		this.transCtrl 	= transCtrl;
	}
	
	public CoinRegistry getCoinRegistry()
	{
		if(cReg == null)
		{
			VmcsDAOFactory daoFactory = VmcsDAOFactory.getDAOFactory(VmcsDAOFactory.StorageType.JAVAPROPERTIES);
			try {
				cReg = daoFactory.getCoinRegistryDAO().getCoinRegistry();
			} catch (VMCSException e) {
				e.printStackTrace();
			}
		}
		
		return cReg;
	}
	
	/**
	 * Commences the receiving of coins. Activates the Coin Input Box and updates the total money inserted
	 */
	public void startReceive() {
		GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.AllowCoinReceive, true);
	}
	
	/**
	 * Receieves a coin, and checks the weight, adding to the array of coins entered if correct.
	 * @param weight Weight of the coin entered.
	 */
	public void receiveCoin(double weight)
	{
		GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.AllowCoinReceive, false);
		CoinHandler handler = CoinHandlerList.getFirstHandler();
		Coin coin = handler.handleCoin(weight);
		
		if(coin != null)
		{
			System.out.println("Input coin value is :" + coin.getValue());
			coins.add(coin);
			totalInserted += coin.getValue();
			GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.ValidCoinInserted, totalInserted);
			GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.InvalidCoinInserted, false);
			
			if(! transCtrl.processMoneyReceived(totalInserted)) {
				GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.AllowCoinReceive, true);
			}
			else {
				transCtrl.completeTransaction();
			}
		}
		else
		{
			GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.InvalidCoinInserted, true);
			GUIChangeManager.getInstance().fireEvent(GUIChangeManagerEvent.AllowCoinReceive, true);
		}
	}
	
	/**
	 * Instructs the Cash Store to update its totals and reset the Total Money inserted display to 0
	 * @return True if Store Cash Success, false if otherwise
	 */
	public boolean storeCash() {
		
		boolean storeSuccess = true;
		
		for(Coin c : coins) {
			if(! this.transCtrl.getMainController().getMachineryController().storeCoin(c)) {
				storeSuccess = false;
			}
		}
		resetCoinVariables();
		return storeSuccess;
	}
	
	/**
	 * Handles refunding of cash to the customer
	 */
	public void refundCash() {
		resetCoinVariables();
	}
	
	/**
	 * Gets the total amount of money inserted
	 * @return
	 */
	public int getTotalInserted() {
		return totalInserted;
	}
	
	/**
	 * Resets the coin inputs
	 */
	private void resetCoinVariables() {
		coins 			= new ArrayList<Coin>();
		totalInserted 	= 0;
	}
}
